<template>
	<div
		v-if="show"
		:class="[
			'popup__wrapper',
			`popup__wrapper--${direction}`,
			`is-${status ? 'open' : 'close'}`
		]"
		@touchmove.stop.prevent
	>
		<div class="popup__modal" :class="{ 'is-mask': mask }" @click="modalClose"></div>

		<div :class="['popup']" :style="{ height, width, backgroundColor, borderRadius }">
			<div class="popup__container" :style="{ padding }">
				<slot />
			</div>
		</div>
	</div>
</template>
<script>
/**
 * popup 弹出框
 * @description 支持各方向的弹出框
 * @property {Boolean} visible 是否可见
 * @property {Function} beforeClose 关闭前钩子函数
 * @property {String} direction 弹出方向, top | right | bottom | left | center，默认left
 * @property {Boolean} closeOnClickModal 点击遮罩层是否关闭，默认true
 * @property {String, Number} size 弹出框大小，默认auto
 * @property {String} backgroundColor 背景颜色，默认#fff
 * @property {String, Number} borderRadius 内容圆角
 * @property {String, Number} padding 内容内间据，默认20
 * @example <popup :visible.sync="visible">Hello !</popup>
 */

export default {
	name: "Popup",
	props: {
		// 是否可见
		visible: Boolean,
		// 关闭前钩子函数
		beforeClose: Function,
		// 弹出方向
		direction: {
			type: String,
			default: "center"
		},
		// 点击遮罩层是否关闭
		closeOnClickModal: {
			type: Boolean,
			default: true
		},
		// 显示遮罩
		mask: {
			type: Boolean,
			default: false
		},
		// 弹出框大小
		size: {
			type: [String, Number],
			default: "auto"
		},
		// 背景颜色
		backgroundColor: {
			type: String
		},
		// 内容圆角
		borderRadius: {
			type: [String, Number],
			default: "5px"
		},
		// 内容内间据
		padding: {
			type: [String, Number],
			default: 0
		}
	},

	data() {
		return {
			show: false,
			status: false,
			timer: null
		};
	},

	computed: {
		height() {
			let height = "";
			switch (this.direction) {
				case "top":
					break;
				case "bottom":
					height = this.size;
					break;
				case "left":
					break;
				case "right":
					height = "100%";
					break;
			}
			return height;
		},

		width() {
			let width = "";
			switch (this.direction) {
				case "top":
				case "bottom":
					width = "100%";
					break;
				case "left":
					break;
				case "right":
					break;
				case "center":
					width = this.size;
					break;
			}
			return width;
		}
	},

	watch: {
		visible: {
			immediate: true,
			handler(val) {
				if (val) {
					this.open();
				} else {
					this.close();
				}
			}
		}
	},

	methods: {
		open() {
			if (!this.show) {
				this.show = true;

				this.$emit("update:visible", true);
				this.$emit("open");

				clearTimeout(this.timer);

				this.timer = setTimeout(() => {
					this.status = true;
				}, 50);
			}
		},

		close() {
			if (this.status) {
				const done = () => {
					this.status = false;

					this.$emit("update:visible", false);
					this.$emit("close");

					clearTimeout(this.timer);

					this.timer = setTimeout(() => {
						this.show = false;
					}, 300);
				};

				if (this.beforeClose) {
					this.beforeClose(done);
				} else {
					done();
				}
			}
		},

		modalClose() {
			if (!this.closeOnClickModal) {
				return false;
			}
			this.close();
		}
	}
};
</script>
<style lang="scss">
.popup__wrapper {
	z-index: 999;
	position: fixed;
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
	opacity: 0;
	transition: all 0.3s;
	pointer-events: none;
}
.popup__wrapper.is-open {
	opacity: 1;
	pointer-events: auto;
}
.popup__wrapper.is-open .popup {
	transition: all 0.4s;
	transform: translate(0, 0);
}
.popup__wrapper::after {
	content: "";
	display: inline-block;
	height: 100%;
	width: 0;
	vertical-align: middle;
}
.popup__wrapper .popup__modal {
	height: 100%;
	width: 100%;
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
}
.popup__wrapper .popup__modal.is-mask {
	background-color: rgba(0, 0, 0, 0.4);
}
.popup__wrapper .popup {
	display: flex;
	flex-direction: column;
	position: absolute;
	transition: all 0.3s;
	box-sizing: border-box;
}
.popup__wrapper .popup__container {
	height: 100%;
}
.popup__wrapper--left .popup {
	transform: translateX(-100%);
	top: 0;
	left: 0;
}
.popup__wrapper--right .popup {
	transform: translateX(100%);
	right: 0;
	top: 0;
}
.popup__wrapper--top .popup {
	transform: translateY(-100%);
	left: 0;
	top: 0;
}

.popup__wrapper--bottom .popup {
	transform: translateY(100%);
	left: 0;
	bottom: 0;
}
.popup__wrapper--center {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
}
.popup__wrapper--center .popup {
	transform: scale(1.3);
}
</style>
